﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace theguineasyndrome
{
    public class PortalableElement : ObstacleElement
    {
        private List<Portal> portals;

        public PortalableElement(Level level, Texture2D texture, Vector2 position)
            : base(level, texture, position)
        {
            portals = new List<Portal>();
        }

        public void addPortal(Portal portal)
        {
            portals.Add(portal);
        }

        public void removePortal(Portal portal)
        {
            portals.Remove(portal);
        }

        public List<Portal> getPortalsAt(LevelElement.Side side)
        {
            List<Portal> sidePortals = new List<Portal>();

            foreach (Portal portal in portals)
                if (portal.getSide() == side)
                    sidePortals.Add(portal);

            return sidePortals;
        }

        public override void Draw(SpriteBatch spriteBatch, Camera camera)
        {
            base.Draw(spriteBatch, camera);
            foreach (Portal portal in portals)
                portal.Draw(spriteBatch, camera);
        }

        public override void repulseCharacterX(Character character, Rectangle intersection, ref bool moveLeft, ref bool moveRight)
        {
            Vector2 obstacleCenter = Center;
            Vector2 characterCenter = character.Center;
            Vector2 characterPosition = character.Position;

            Portal currentPortal = character.getCurrentPortal();

            if (currentPortal != null)
            {
                LevelElement.Side portalSide = currentPortal.getSide();

                if (portalSide == LevelElement.Side.TOP)
                {
                    if (character.SquareTop >= currentPortal.CenterY)
                        currentPortal.setDestination(character);
                }
                else if (portalSide == LevelElement.Side.BOTTOM)
                {
                    if (character.SquareBottom <= currentPortal.CenterY)
                        currentPortal.setDestination(character);
                }
                else if (portalSide == LevelElement.Side.LEFT)
                {
                    if (character.SquareLeft >= currentPortal.CenterX)
                        currentPortal.setDestination(character);
                }
                else if (portalSide == LevelElement.Side.RIGHT)
                {
                    if (character.SquareRight <= currentPortal.CenterX)
                        currentPortal.setDestination(character);
                }
            }
            else if (intersection.Width < intersection.Height)
            {
                if (characterCenter.X < obstacleCenter.X) // move left
                {
                    List<Portal> leftPortals = getPortalsAt(LevelElement.Side.LEFT);
                    Portal leftPortal = null;

                    foreach (Portal portal in leftPortals)
                    {
                        if (character.SquareTop >= portal.Top && character.SquareBottom <= portal.Bottom)
                        {
                            leftPortal = portal;
                            break;
                        }
                    }

                    if (leftPortal != null && leftPortal.getPairPortal() != null)
                    {
                        character.setCurrentPortal(leftPortal);
                    }
                    else
                    {
                        character.setCurrentPortal(null);
                        character.setPosition(new Vector2(Left - character.Width / 2, characterPosition.Y));
                        moveLeft = true;
                        character.SpeedX = 0;
                    }
                }
                else if (characterCenter.X > obstacleCenter.X) // move right
                {
                    List<Portal> rightPortals = getPortalsAt(LevelElement.Side.RIGHT);
                    Portal rightPortal = null;

                    foreach (Portal portal in rightPortals)
                    {
                        if (character.SquareTop >= portal.Top && character.SquareBottom <= portal.Bottom)
                        {
                            rightPortal = portal;
                            break;
                        }
                    }

                    if (rightPortal != null && rightPortal.getPairPortal() != null)
                    {
                        character.setCurrentPortal(rightPortal);
                    }
                    else
                    {
                        character.setCurrentPortal(null);
                        character.setPosition(new Vector2(Right + character.Width / 2, characterPosition.Y));
                        moveRight = true;
                        character.SpeedX = 0;
                    }
                }
            }
        }

        public override void repulseCharacterY(Character character, Rectangle intersection, ref bool moveUp, ref bool moveDown)
        {
            Vector2 obstacleCenter = Center;
            Vector2 characterCenter = character.Center;
            Vector2 characterPosition = character.Position;

            if (character.getCurrentPortal() == null && intersection.Width > intersection.Height)
            {
                if (characterCenter.Y < obstacleCenter.Y) // move up
                {
                    List<Portal> topPortals = getPortalsAt(LevelElement.Side.TOP);
                    Portal topPortal = null;

                    foreach (Portal portal in topPortals)
                    {
                        if (character.SquareLeft >= portal.Left && character.SquareRight <= portal.Right)
                        {
                            topPortal = portal;
                            break;
                        }
                    }

                    if (topPortal != null && topPortal.getPairPortal() != null)
                    {
                        character.setCurrentPortal(topPortal);
                    }
                    else
                    {
                        character.setCurrentPortal(null);
                        character.setPosition(new Vector2(characterPosition.X, CollisionTop + 1));
                        moveUp = true;
                        character.setObstacleElement(this);
                        character.SpeedY = 0;
                    }
                }
                else if (characterCenter.Y > obstacleCenter.Y) // move down
                {
                    List<Portal> bottomPortals = getPortalsAt(LevelElement.Side.BOTTOM);
                    Portal bottomPortal = null;

                    foreach (Portal portal in bottomPortals)
                    {
                        if (character.SquareLeft >= portal.Left && character.SquareRight <= portal.Right)
                        {
                            bottomPortal = portal;
                            break;
                        }
                    }

                    if (bottomPortal != null && bottomPortal.getPairPortal() != null)
                    {
                        character.setCurrentPortal(bottomPortal);
                    }
                    else
                    {
                        character.setCurrentPortal(null);
                        character.setPosition(new Vector2(characterPosition.X, CollisionBottom + character.Height + 1));
                        moveDown = true;
                        character.SpeedY = 0;
                    }
                }
            }
        }

        public override void repulseLiquidDrop(LiquidDrop drop)
        {
            if (drop is PortalDrop)
            {
                base.repulseLiquidDrop(drop);
            }
            else
            {
                float distLeft = drop.X - Left;
                float distRight = Right - drop.X;
                float distTop = drop.Y - CollisionTop;
                float distBottom = CollisionBottom - drop.Y;

                if (distLeft < distRight && distLeft < distTop && distLeft < distBottom) // move left
                {
                    List<Portal> leftPortals = getPortalsAt(Side.LEFT);
                    Portal currentPortal = null;
                    foreach (Portal portal in leftPortals)
                    {
                        if (portal.Top <= drop.Top && drop.Bottom <= portal.Bottom)
                        {
                            currentPortal = portal;
                            break;
                        }
                    }
                    if (currentPortal != null && currentPortal.getPairPortal() != null)
                    {
                        drop.CurrentPortal = currentPortal;
                        if (drop.Left >= currentPortal.CenterX)
                        {
                            currentPortal.setDropDestination(drop);
                        }
                    }
                    else
                    {
                        drop.X = Left - drop.getRadius();
                        drop.NextDropSpeed = new Vector2(-drop.SpeedX, drop.SpeedY);
                        drop.setKillingObstacle(this);
                    }
                }
                else if (distRight < distTop && distRight < distBottom) // move right
                {
                    List<Portal> rightPortals = getPortalsAt(Side.RIGHT);
                    Portal currentPortal = null;
                    foreach (Portal portal in rightPortals)
                    {
                        if (portal.Top <= drop.Top && drop.Bottom <= portal.Bottom)
                        {
                            currentPortal = portal;
                            break;
                        }
                    }
                    if (currentPortal != null && currentPortal.getPairPortal() != null)
                    {
                        drop.CurrentPortal = currentPortal;
                        if (drop.Right <= currentPortal.CenterX)
                        {
                            currentPortal.setDropDestination(drop);
                        }
                    }
                    else
                    {
                        drop.X = Right + drop.getRadius();
                        drop.NextDropSpeed = new Vector2(-drop.SpeedX, drop.SpeedY);
                        drop.setKillingObstacle(this);
                    }
                }
                else if (distTop < distBottom) // move up
                {
                    List<Portal> topPortals = getPortalsAt(Side.TOP);
                    Portal currentPortal = null;
                    foreach (Portal portal in topPortals)
                    {
                        if (portal.Left <= drop.Left && drop.Left <= portal.Right)
                        {
                            currentPortal = portal;
                            break;
                        }
                    }
                    if (currentPortal != null && currentPortal.getPairPortal() != null)
                    {
                        drop.CurrentPortal = currentPortal;
                        if (drop.Top >= currentPortal.CenterY)
                        {
                            currentPortal.setDropDestination(drop);
                        }
                    }
                    else
                    {
                        drop.Y = CollisionTop - drop.getRadius();
                        drop.NextDropSpeed = new Vector2(drop.SpeedX, -drop.SpeedY);
                        drop.setKillingObstacle(this);
                    }
                }
                else // move down
                {
                    List<Portal> bottomPortals = getPortalsAt(Side.BOTTOM);
                    Portal currentPortal = null;
                    foreach (Portal portal in bottomPortals)
                    {
                        if (portal.Left <= drop.Left && drop.Left <= portal.Right)
                        {
                            currentPortal = portal;
                            break;
                        }
                    }
                    if (currentPortal != null && currentPortal.getPairPortal() != null)
                    {
                        drop.CurrentPortal = currentPortal;
                        if (drop.Bottom <= currentPortal.CenterY)
                        {
                            currentPortal.setDropDestination(drop);
                        }
                    }
                    else
                    {
                        drop.Y = CollisionBottom + drop.getRadius();
                        drop.NextDropSpeed = new Vector2(drop.SpeedX, -drop.SpeedY);
                        drop.setKillingObstacle(this);
                    }
                }
            }
        }

    }
}
